﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.Adapter;
using Microsoft.TeamFoundation.Warehouse;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common;

using System.Diagnostics;
using System.Globalization;


using Microsoft.SharePoint;

namespace Sogeti.TeamFoundation.TeamProjectMetadata.Adapter
{



    public class TFSSCoreCardAdapter : IWarehouseAdapter
    {
        private bool _stopRequested = false;
        private IDataStore _DataStore;

        
        private ICommonStructureService _CommonStructureService;



        public TFSSCoreCardAdapter()
        {
        }


        #region IWarehouseAdapter Interface




      
        public void RequestStop()
        {
            _stopRequested = true;
            LogMessage("Request Stop: A Stop Request was recieved.  Setting _stopRequested to True.");
        }





    
        public void Initialize(IDataStore ds)
        {
            string url;
            TeamFoundationServer tfs;
            _DataStore = ds;

            LogMessage("Initialization Beginning");



        

          // The DataStore is passed in from the Warehouse Service.  It is the
            // API access point to the TFSWarehouse database.
            if (_DataStore == null)
            {
                throw new Exception("Null data store.");
            }

            //Retrieve TFS instance to support retrieval of TFS Services
            url = Microsoft.TeamFoundation.Server.TeamFoundationApplication.TfsNameUrl;
            tfs = TeamFoundationServerFactory.GetServer(url);
            if (tfs == null)
            {
                throw new Exception("TF Server instance not obtained for TFS url: " + url);
            }
            LogMessage("  Retrieved TFS reference at " + url);


            // The TFS Common Structure Service holds the Team Project information.
            _CommonStructureService = (ICommonStructureService)tfs.GetService(typeof(ICommonStructureService));
            if (_CommonStructureService == null)
            {
                throw new Exception("Common Structure Service instance not obtained for TFS url: " + url);
            }
            LogMessage("  Retrieved CommonStructureStore");
          
            LogMessage("Initialization Complete");
        }


        public SchemaChangesResult MakeSchemaChanges()
        {
            LogMessage("MakeSchemaChanges: Starting");

            SchemaChangesResult result = SchemaChangesResult.NoChanges;

            //Get the current data warehouse configuration  
            WarehouseConfig warehouseConfig = _DataStore.GetWarehouseConfig();

            //The IWarehouseAdapter.MakeSchemaChanges can be called many times in one session 
            //so check to see if the fact and dimension were already created 


          
              
            if (!_stopRequested)
            {
                LogMessage("  Beginning Save of schema changes");

                Boolean AssociatedChangeMeasureExist = MeasureExistInFact(warehouseConfig, "Associated Changeset Count","Work Item Changeset"  );
                Boolean ChangeCountMeasureExist= MeasureExistInFact(warehouseConfig, "Changeset Count","Code Churn");


                if(!AssociatedChangeMeasureExist || !ChangeCountMeasureExist){
                    //Starting a Transaction to rollback my changes if they fail 
                    _DataStore.BeginTransaction();
                    try
                    {
                      
                     if( !AssociatedChangeMeasureExist){
                       
                      //Adding to the data warehouse configuration xml file and saving the changes 

                         Measure accChngMeasure = new Measure();
                         accChngMeasure.AggregationFunction = "DistinctCount";
                         accChngMeasure.SourceField = "Changeset";
                         accChngMeasure.Type = "INT";
                         accChngMeasure.Name = "Associated Changeset Count";
                         accChngMeasure.FriendlyName = "Associated Changeset Count";
                         accChngMeasure.Visible = true;

                         _DataStore.Add("Work Item Changeset", accChngMeasure);
                       }

                     if (!ChangeCountMeasureExist)
                     {
                        Measure chgMeasure = new Measure();
                        chgMeasure.AggregationFunction = "DistinctCount";
                        chgMeasure.SourceField = "Changeset";
                        chgMeasure.Type = "INT";
                        chgMeasure.Name = "Changeset Count";
                        chgMeasure.FriendlyName = "Changeset Count";
                        chgMeasure.Visible = true;

                        _DataStore.Add("Code Churn", chgMeasure);
                      }
                      _DataStore.CommitTransaction();
                      result = SchemaChangesResult.ChangesComplete;
                      LogMessage("  Save of schema changes completed successfully");
                    }
                    catch (Exception ex)
                    {
                        LogMessage("  Save of schema changes FAILED.  Exception thrown.");
                        LogMessage(String.Format("    EXCEPTION: {0}\n          {1}", ex.Message, ex.StackTrace));
                        _DataStore.RollbackTransaction();
                        throw;
                    }
                }
            }
            else
            {
                LogMessage("  Save of schema Cancelled.  Stop request processed.");
                result = SchemaChangesResult.StopRequested;
            }

            LogMessage("MakeSchemaChanges: Completed");
            return result;
        }

        private static Boolean MeasureExistInFact(WarehouseConfig warehouseConfig, String name, String factName)
        {
          foreach (Measure m in warehouseConfig.GetFact(factName).Measures)
          {
            if (m.Name == name)
            {
              return true;
            }
          }
          return false;
        }

       
 
       

        #endregion




        #region MakeDataChanges Implementation



        // save any new data changes in the operational store to the data warehouse
        public DataChangesResult MakeDataChanges()
        {
            LogMessage("Dothing to do : Starting");
            return DataChangesResult.ChangesComplete;         
        }

 
        #endregion


      


        private static void LogMessage(string message)
        {
            Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1}: {2}", "[Notion Work Item Links Adapter]", DateTime.Now, message));
        }
    }
}
